import 'dart:collection';

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/app_colors.dart';
import 'package:finance_app/src/common/app_spaces.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/setting_data_entity.dart';
import 'package:finance_app/src/utils/reg_exp_utils.dart';
import 'package:finance_app/src/widgets/common/expandable.dart';
import 'package:finance_app/src/widgets/list_item/list_expandable_item.dart';
import 'package:finance_app/src/widgets/input/search_input_field.dart';
import 'package:finance_app/src/widgets/select/normal_radio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;
import 'default_bottom_sheet.dart';

/// 选择标签
///
/// 返回实体类 SettingDataCategory
showCategoryBottomSheet(
    BuildContext context, SettingDataCategory currentSelectCategory) async {
  SettingDataCategory _currentSelectCode = currentSelectCategory;
  await showDefaultBottomSheet(
    context,
    child: CategoryWidget(
      currentSelectCode: currentSelectCategory,
      selectCallBack: (data) {
        _currentSelectCode = data;
      },
      categories: Config.settingData.category,
    ),
    title: S.current.select_category,
    isScrollControlled: true,
  );
  return _currentSelectCode;
}

class CategoryWidget extends StatefulWidget {
  final SettingDataCategory currentSelectCode;
  final ValueChanged<SettingDataCategory> selectCallBack;
  final ScrollController scrollController;
  final List<SettingDataCategory> categories;
  final List<int> recentIds;
  final bool isSinglePage;
  final bool isGroupRecommended;

  CategoryWidget(
      {Key key,
      this.isGroupRecommended = false,
      this.isSinglePage = false,
      this.categories,
      this.recentIds,
      this.currentSelectCode,
      this.selectCallBack,
      this.scrollController})
      : super(key: key);

  @override
  _CategoryWidgetState createState() => _CategoryWidgetState();
}

class _CategoryWidgetState extends State<CategoryWidget> {
  TextEditingController _searchController = TextEditingController();
  FocusNode _searchFocusNode = FocusNode();
  ScrollController _scrollController;
  LinkedHashMap<String, Map<String, dynamic>> data = LinkedHashMap();
  SettingDataCategory _currentSelectCategory;
  List<ExpandableController> expandControllerList = [];

  bool isShowMore = false;

  @override
  void initState() {
    super.initState();
    _scrollController = widget.scrollController ?? ScrollController();
    Map<String, Map<String, dynamic>> _data = {};
    List<SettingDataCategory> categories = List.of(widget.categories ?? []);

    if (widget.recentIds != null) {
      _data['Recently Used'] = {};
      expandControllerList.add(ExpandableController(initialExpanded: true));
      widget.recentIds.forEach((id) {
        SettingDataCategory cate = categories
            .firstWhere((element) => element.id == id, orElse: () => null);
        if (cate != null) {
          SettingDataCategory newcate =
              SettingDataCategory().fromJson(cate.toJson());

          newcate.categoryGroup = 'Recently Used';
          Map groupMap = _data['Recently Used'];
          groupMap[newcate.name] = newcate;
        }
      });
    }

    if (widget.isGroupRecommended == true) {
      _data['Recommended'] = {};
      expandControllerList.add(ExpandableController(initialExpanded: true));
      // } else {
      // _data['General'] = {};
      // expandControllerList.add(ExpandableController(initialExpanded: true));
      // _data['Marketing & selling'] = {};
      // expandControllerList.add(ExpandableController(initialExpanded: true));
    }
    // categories.sort((a, b) {
    //   // if ((a.categoryGroup.startsWith('G') ||
    //   //     a.categoryGroup.startsWith('M') && b.categoryGroup.startsWith('G') ||
    //   //     b.categoryGroup.startsWith('M'))) {
    //   //   return a.categoryGroup.compareTo(b.categoryGroup);
    //   // }
    //   // if (a.categoryGroup.startsWith('G') || a.categoryGroup.startsWith('M')) {
    //   //   return 1;
    //   // }
    //   // if (b.categoryGroup.startsWith('G') || b.categoryGroup.startsWith('M')) {
    //   //   return 0;
    //   // }
    //   return a.name.compareTo(b.name);
    // });

    for (final item in categories) {
      if (item.isRecommended == 1 && widget.isGroupRecommended == true) {
        Map groupMap = _data['Recommended'];
        groupMap[item.name] = item;
      } else {
        if (_data.containsKey(item.categoryGroup)) {
          Map groupMap = _data[item.categoryGroup];
          groupMap[item.name] = item;
        } else {
          _data[item.categoryGroup] = {
            item.name: item,
          };
          expandControllerList.add(ExpandableController(initialExpanded: true));
        }
      }
    }

    data = _data;
    // if (data.isNotEmpty) {
    //   currentSelectGroup = data.keys.first;
    // }
    // _headerKey = List.generate(data.keys.length, (index) => GlobalKey());
    _currentSelectCategory = widget.currentSelectCode;
    _searchController.addListener(_handleSearchInput);
  }

  void _handleSearchInput() {
    setState(() {});
  }

  void _onChangeShowMore() {
    setState(() {
      isShowMore = !isShowMore;
    });
  }

  bool _onSearchInputGroup(MapEntry<String, dynamic> element) {
    String searchInput = _searchController.text;
    return element.value
        .toString()
        .contains(RegExpUtils.getSearchRegExp(searchInput));
  }

  dynamic _onSearchInputItem(Map<String, dynamic> element) {
    String searchInput = _searchController.text;
    Map<String, dynamic> data = {};
    for (final item in element.entries) {
      final category = item.value as SettingDataCategory;
      if (RegExpUtils.getSearchRegExp(searchInput).hasMatch(item.key) ||
          RegExpUtils.getSearchRegExp(searchInput).hasMatch(category.key)) {
        data[item.key] = item.value;
      }
    }
    return data;
  }

  @override
  void dispose() {
    super.dispose();
    _searchController.dispose();
    _searchFocusNode.dispose();
  }

  void onChangeSelectCode(SettingDataCategory value) {
    if (value != _currentSelectCategory) {
      setState(() {
        _currentSelectCategory = value;
      });
      widget.selectCallBack?.call(_currentSelectCategory);
    }
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> slivers;
    if (_searchController.text.isNotEmpty) {
      slivers = data.entries
          .toList()
          .where(_onSearchInputGroup)
          .map((e) => buildSliver(e.key, _onSearchInputItem(e.value)))
          .toList();
    } else {
      if (isShowMore) {
        slivers = data.entries
            .toList()
            .map((e) => buildSliver(e.key, e.value))
            .toList();
      } else {
        int length = data.entries.length;
        slivers = data.entries
            .toList()
            .getRange(0, math.min(length, widget.recentIds == null ? 1 : 2))
            .map((e) => buildSliver(e.key, e.value))
            .toList();
      }

      slivers.add(PressedOpacityButton(
        onPressed: _onChangeShowMore,
        padding:
            EdgeInsets.symmetric(horizontal: getDp(25), vertical: getDp(20)),
        child: Text(
          isShowMore ? S.current.show_less : S.current.see_more,
          style: TextStyle(
            color: aceBlueColor,
            fontSize: getSp(18),
            fontWeight: FontWeight.w700,
            height: 18 / 16,
          ),
        ),
      ));
    }

    return Column(
      children: [
        if (widget.isSinglePage == true) AppSpaces.h20,
        SearchInputField(
          key: ValueKey('Search Input'),
          controller: _searchController,
          focusNode: _searchFocusNode,
        ),
        // if (_searchController.text.isEmpty)
        //   Container(
        //     height: getDp(82),
        //     alignment: Alignment.centerLeft,
        //     child: ListView.builder(
        //       padding: EdgeInsets.symmetric(horizontal: getDp(9)),
        //       scrollDirection: Axis.horizontal,
        //       itemBuilder: _buildItems,
        //       itemCount: data.keys.length,
        //     ),
        //   )
        // else
        AppSpaces.h20,
        Expanded(
            child: CupertinoScrollbar(
          child: ListView(
            controller: _scrollController,
            children: slivers,
          ),
        )),
      ],
    );
  }

  // Widget _buildItems(BuildContext context, int index) {
  //   final item = data.keys.toList()[index];
  //   final isSelect = item == currentSelectGroup;
  //   return Center(
  //     child: PressedOpacityButton(
  //         padding: EdgeInsets.symmetric(
  //           horizontal: getDp(7),
  //         ),
  //         onPressed: () {
  //           onSelect(item);
  //         },
  //         child: Container(
  //           padding:
  //               EdgeInsets.symmetric(horizontal: getDp(10), vertical: getDp(8)),
  //           decoration: BoxDecoration(
  //               borderRadius: BorderRadius.circular(getDp(5)),
  //               color: isSelect ? aceBlueColor : Colors.white,
  //               border: Border.all(
  //                 color: aceBlueColor,
  //                 width: getDp(1),
  //               )),
  //           child: Text(
  //             '$item',
  //             style: TextStyle(
  //               color: isSelect ? Colors.white : aceBlueColor,
  //               fontSize: getSp(14),
  //               fontWeight: FontWeight.w700,
  //               height: 1,
  //             ),
  //           ),
  //         )),
  //   );
  // }

  // void onSelect(String value) {
  //   setState(() {
  //     currentSelectGroup = value;
  //   });
  //   int index = data.keys.toList().indexOf(value);
  //   final _key = _headerKey[index];
  //   final RenderObject contextObject = _key.currentContext.findRenderObject();
  //   final RenderAbstractViewport viewport =
  //       RenderAbstractViewport.of(contextObject);
  //   assert(viewport != null);
  //   final topOffset = math.max(_scrollController.position.minScrollExtent,
  //       viewport.getOffsetToReveal(contextObject, 0.0).offset);
  //   _scrollController.position.animateTo(topOffset,
  //       duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
  // }

  Widget buildSliver(String title, Map<String, dynamic> data) {
    final groupName = widget.categories.firstWhere(
        (element) => element.categoryGroup == title,
        orElse: () => null);
    final String _title = groupName?.categoryGroup == null
        ? (widget.isGroupRecommended == true ? 'Recommended' : 'Recently Used')
        : groupName.categoryGroup;
    return ListExpandableItem(
      controller: expandControllerList[this.data.keys.toList().indexOf(title)],
      title: _title,
      content: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: List.generate(
            data.entries.length, (index) => buildSliverItem(data, index)),
      ),
    );
  }

  // SliverStickyHeader(
  //   header: buildSliverHeader(title: title),
  //   sliver: SliverList(
  //     delegate: SliverChildBuilderDelegate(
  //       (context, i) => buildSliverItem(data, i),
  //       childCount: data.entries.length,
  //     ),
  //   ),
  // );

  Widget buildSliverItem(Map<String, dynamic> data, int i) {
    SettingDataCategory category = data.entries.toList()[i].value;
    bool isSelect = _currentSelectCategory?.id == category?.id;
    return PressedOpacityButton(
      onPressed: () => onChangeSelectCode(category),
      padding: EdgeInsets.symmetric(
        horizontal: getDp(30),
        vertical: getDp(12),
      ),
      child: NormalRadio(
        isSelect: isSelect,
        title: data.entries.toList()[i].key,
        isFix: true,
      ),
    );
  }

// Widget buildSliverHeader({String title}) {
//   final groupName = Config.settingData.categoryGroup
//       .firstWhere((element) => element.key == title, orElse: () => null);
//   final String _title = groupName?.name == null ? "*" : groupName.name;
//   int index = data.keys.toList().indexOf(title);
//   return ListHeaderItem(
//     key: _headerKey[index],
//     title: _title,
//   );
// }

}
